﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace System {
    public static partial class Extention {
        #region Split
        public static string[] Split(this string str,string separator) {
            return str.Split(new[] { separator },StringSplitOptions.None);
        }
        public static string[] Split(this string str,string separator,StringSplitOptions options) {
            return str.Split(new[] { separator },options);
        }
        #endregion
       /// <summary>
        /// 计算字符串中子串出现的次数
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="substring">子串</param>
        /// <returns>出现的次数</returns>
        public static int SubstringCount(this string str, string substring) {
            if (str.Contains(substring)){
                string strReplaced = str.Replace(substring, "");
                return (str.Length - strReplaced.Length) / substring.Length;
            }
            return 0;
        }
        #region 正则表达式
        /// <summary>
        /// 正则表达式
        /// </summary>
        public static bool IsMatch(this string s,string pattern) {
            if(s == null) return false;
            else return Regex.IsMatch(s,pattern);
        }
        /// <summary>
        /// 正则表达式
        /// </summary>
        public static string Match(this string s,string pattern) {
            if(s == null) return "";
            return Regex.Match(s,pattern).Value;
        }
        #endregion

        /// <summary>
        /// 转换类型
        /// </summary>
        public static T ToConvert<T>(this string s) {
            return Utils.GetObjTranNull<T>(s);
        }
        #region 字符串判断
        /// <summary>
        /// 判断URL
        /// </summary>
        public static bool IsUrl(this string str) {
            if(string.IsNullOrEmpty(str))
                return false;
            string Url = @"(http://)?([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";
            return Regex.IsMatch(str,Url);
        }
        /// <summary>
        /// 判断是不是正确的手机号码
        /// </summary>
        public static bool IsPhoneNo(this string input) {
            if(string.IsNullOrEmpty(input))
                return false;
            if(input.Length != 11)
                return false;

            if(new Regex(@"^1[3578][01379]\d{8}$").IsMatch(input)
                || new Regex(@"^1[34578][01256]\d{8}").IsMatch(input)
                || new Regex(@"^(1[012345678]\d{8}|1[345678][0123456789]\d{8})$").IsMatch(input)
                )
                return true;
            return false;
        }
        #endregion


        /// <summary>
        /// 获得 当前操作系统目录分隔符的路径
        /// </summary>
        /// <param name="originalString">原始路径字符串</param>
        /// <returns></returns>
        public static string GetOSPlatformPath(this string originalString) {
            var sp = Path.DirectorySeparatorChar;
            var win = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
            return win ? originalString.Replace('/',sp) : originalString.Replace('\\',sp);
        }
        #region 文件操作
        /// <summary>
        /// 建立文件夹
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static bool CreateDir(this string name) {
            if(!Directory.Exists(name)) {
                Directory.CreateDirectory(name);
            }
            return true;
        }
        /// <summary>
        /// 返回文件是否存在
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <returns>是否存在</returns>
        public static bool FileExists(this string filename) {
            return System.IO.File.Exists(filename);
        }
        public static void CreateDirectory(this string path) {
            Directory.CreateDirectory(path);
        }
        public static void WriteText(this string path,string contents) {
            File.WriteAllText(path,contents);
        }
        public static void DeleteFile(this string path) {
            if(File.Exists(path)) File.Delete(path);
        }
        #endregion
        /// <summary>
        /// 转换为MD5加密后的字符串（默认加密为32位）
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ToMD5String(this string str) {
            MD5 md5 = MD5.Create();
            byte[] inputBytes = Encoding.UTF8.GetBytes(str);
            byte[] hashBytes = md5.ComputeHash(inputBytes);
            StringBuilder sb = new StringBuilder();
            for(int i = 0;i < hashBytes.Length;i++) {
                sb.Append(hashBytes[i].ToString("x2"));
            }
            md5.Dispose();
            return sb.ToString();
        }
        /// <summary>
        /// 将ASCII码形式的字符串转为对应字节数组
        /// 注：一个字节一个ASCII码字符
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns></returns>
        public static byte[] ToASCIIBytes(this string str) {
            return str.ToList().Select(x => (byte)x).ToArray();
        }
        #region SafeSql
        /// <summary>
        ///isInt true: 1,2,3 false: '1','2','3'
        /// </summary>
        public static string ToSql(this string[] str,bool isInt) {
            if(isInt) {
                return string.Join(",",str);
            } else {
                StringBuilder idsStr = new StringBuilder();
                for(int i = 0;i < str.Length;i++) {
                    if(i > 0) {
                        idsStr.Append(",");
                    }
                    idsStr.Append("'").Append(str[i]).Append("'");
                }
                return idsStr.ToString();
            }
        }
        /// <summary>
        ///isInt true: 1,2,3 false: '1','2','3'
        /// </summary>
        public static string ToSql(this List<string> str,bool isInt) {
            if(isInt) {
                return string.Join(",",str);
            } else {
                StringBuilder idsStr = new StringBuilder();
                for(int i = 0;i < str.Count;i++) {
                    if(i > 0) {
                        idsStr.Append(",");
                    }
                    idsStr.Append("'").Append(str[i]).Append("'");
                }
                return idsStr.ToString();
            }
        }
        /// <summary>
        /// 从脚本获取SQL命令 
        /// </summary>
        public static IList<string> ToSqlCommands(this string sql) {
            var commands = new List<string>();
            sql = Regex.Replace(sql,@"\\\r?\n",string.Empty);
            var batches = Regex.Split(sql,@"^\s*(GO[ \t]+[0-9]+|GO)(?:\s+|$)",RegexOptions.IgnoreCase | RegexOptions.Multiline);
            for(var i = 0;i < batches.Length;i++) {
                if(string.IsNullOrWhiteSpace(batches[i]) || batches[i].StartsWith("GO",StringComparison.OrdinalIgnoreCase))
                    continue;
                var count = 1;
                if(i != batches.Length - 1 && batches[i + 1].StartsWith("GO",StringComparison.OrdinalIgnoreCase)) {
                    var match = Regex.Match(batches[i + 1],"([0-9]+)");
                    if(match.Success)
                        count = int.Parse(match.Value);
                }
                var builder = new StringBuilder();
                for(var j = 0;j < count;j++) {
                    builder.Append(batches[i]);
                    if(i == batches.Length - 1)
                        builder.AppendLine();
                }
                commands.Add(builder.ToString());
            }
            return commands;
        }
        /// <summary>
        /// 过滤sql
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ReplaceSql(this string str) {
            str = str.Replace("'","").Replace("--"," ").Replace(";","");
            return str;
        }
        /// <summary>
        /// 过滤查询sql
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string FilterDangerSql(this string str) {
            if(str.IsNull()) return "";
            str = str.ReplaceIgnoreCase("DELETE ","").ReplaceIgnoreCase("UPDATE ","").ReplaceIgnoreCase("INSERT ","").ReplaceIgnoreCase("DROP ","").ReplaceIgnoreCase("ALTER ","");
            return str;
        }
        /// <summary>
        /// 是否安全字符串SQL，例如包含"slect insert"等注入关键字
        /// </summary>
        public static bool IsSafeSQL(this string s) {
            bool ReturnValue = true;
            try {
                if(s.Trim() != "") {
                    string SqlStr = "exec|insert+|select+|delete|update|count|chr|mid|master+|truncate|char|declare|drop+|drop+table|creat+|create|*|iframe|script|";
                    SqlStr += "exec+|insert|delete+|update+|count(|count+|chr+|+mid(|+mid+|+master+|truncate+|char+|+char(|declare+|drop+table|creat+table";
                    string[] anySqlStr = SqlStr.Split('|');
                    foreach(string ss in anySqlStr) {
                        if(s.ToLower().IndexOf(ss) >= 0) {
                            ReturnValue = false;
                            break;
                        }
                    }
                }
            } catch {
                ReturnValue = false;
            }
            return ReturnValue;
        }
        #endregion

        #region JsonConvert
        /// <summary>
        /// 将XML字符串反序列化为对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="xmlStr">XML字符串</param>
        /// <returns></returns>
        public static T XmlStrToObject<T>(this string xmlStr) {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlStr);
            string jsonJsonStr = JsonConvert.SerializeXmlNode(doc);
            return JsonConvert.DeserializeObject<T>(jsonJsonStr);
        }
        /// <summary>
        /// 将XML字符串反序列化为对象
        /// </summary>
        /// <param name="xmlStr">XML字符串</param>
        /// <returns></returns>
        public static JObject XmlStrToJObject(this string xmlStr) {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlStr);
            string jsonJsonStr = JsonConvert.SerializeXmlNode(doc);
            return JsonConvert.DeserializeObject<JObject>(jsonJsonStr);
        }
        /// <summary>
        /// 将Json字符串反序列化为对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="jsonStr">Json字符串</param>
        /// <returns></returns>
        public static T ToObject<T>(this string jsonStr) {
            return JsonConvert.DeserializeObject<T>(jsonStr);
        }
        public static List<T> ToList<T>(this string jsonStr) {
            try {
                return string.IsNullOrEmpty(jsonStr) ? null : JsonConvert.DeserializeObject<List<T>>(jsonStr);
            } catch(Exception ex) {
                throw new Exception(ex.Message);
            }
        }
        /// <summary>
        /// 将Json字符串转为DataTable
        /// </summary>
        /// <param name="jsonStr">Json字符串</param>
        /// <returns></returns>
        public static DataTable ToDataTable(this string jsonStr) {
            return jsonStr == null ? null : JsonConvert.DeserializeObject<DataTable>(jsonStr);
        }
        /// <summary>
        /// 将Json字符串转为JObject
        /// </summary>
        /// <param name="jsonStr">Json字符串</param>
        /// <returns></returns>
        public static JObject ToJObject(this string jsonStr) {
            return jsonStr == null ? JObject.Parse("{}") : JObject.Parse(jsonStr.Replace("&nbsp;",""));
        }
        /// <summary>
        /// 将Json字符串转为JArray
        /// </summary>
        /// <param name="jsonStr">Json字符串</param>
        /// <returns></returns>
        public static JArray ToJArray(this string jsonStr) {
            return jsonStr == null ? JArray.Parse("[]") : JArray.Parse(jsonStr.Replace("&nbsp;",""));
        }
        #endregion
        /// <summary>
        /// 转为首字母大写
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns></returns>
        public static string ToFirstUpperStr(this string str) {
            return str.Substring(0,1).ToUpper() + str.Substring(1);
        }
        /// <summary>
        /// 转为首字母小写
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns></returns>
        public static string ToFirstLowerStr(this string str) {
            return str.Substring(0,1).ToLower() + str.Substring(1);
        }
        /// <summary>
        /// 转为网络终结点IPEndPoint
        /// </summary>=
        /// <param name="str">字符串</param>
        /// <returns></returns>
        public static IPEndPoint ToIPEndPoint(this string str) {
            IPEndPoint iPEndPoint = null;
            try {
                string[] strArray = str.Split(':').ToArray();
                string addr = strArray[0];
                int port = Convert.ToInt32(strArray[1]);
                iPEndPoint = new IPEndPoint(IPAddress.Parse(addr),port);
            } catch {
                iPEndPoint = null;
            }
            return iPEndPoint;
        }
        /// <summary>
        /// 将枚举类型的文本转为枚举类型
        /// </summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="enumText">枚举文本</param>
        /// <returns></returns>
        public static T ToEnum<T>(this string enumText) {
            var values = typeof(T).GetEnumValues().CastToList<T>();
            return values.Where(x => x.ToString() == enumText).FirstOrDefault();
        }
        public static void OpenProcess(this string s) {
            Process.Start(s);
        }
        public static string ExecuteDOS(this string cmd,out string error) {
            Process process = new Process();
            process.StartInfo.FileName = "cmd.exe";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            process.StandardInput.WriteLine(cmd);
            process.StandardInput.WriteLine("exit");
            error = process.StandardError.ReadToEnd();
            return process.StandardOutput.ReadToEnd();
        }
        /// <summary>
        /// 转全角(SBC case)
        /// </summary>
        /// <param name="input">任意字符串</param>
        /// <returns>全角字符串</returns>
        public static string ToSBC(this string input) {
            char[] c = input.ToCharArray();
            for(int i = 0;i < c.Length;i++) {
                if(c[i] == 32) {
                    c[i] = (char)12288;
                    continue;
                }
                if(c[i] < 127)
                    c[i] = (char)(c[i] + 65248);
            }
            return new string(c);
        }
        /// <summary>
        /// 转半角(DBC case)
        /// </summary>
        /// <param name="input">任意字符串</param>
        /// <returns>半角字符串</returns>
        public static string ToDBC(this string input) {
            char[] c = input.ToCharArray();
            for(int i = 0;i < c.Length;i++) {
                if(c[i] == 12288) {
                    c[i] = (char)32;
                    continue;
                }
                if(c[i] > 65280 && c[i] < 65375)
                    c[i] = (char)(c[i] - 65248);
            }
            return new string(c);
        }
        // 倒置字符串，输入"abcd123"，返回"321dcba"
        public static string Reverse(this string value) {
            char[] input = value.ToCharArray();
            char[] output = new char[value.Length];
            for(int i = 0;i < input.Length;i++)
                output[input.Length - 1 - i] = input[i];
            return new string(output);
        }
        #region 删除最后一个字符之后的字符
        /// <summary>
        /// 删除最后结尾的指定字符后的字符
        /// </summary>
        public static string DelLastChar(this string str,string strchar = ",") {
            return str.Substring(0,str.LastIndexOf(strchar));
        }
        /// <summary>
        /// 删除最后结尾的长度
        /// </summary>
        /// <param name="str"></param>
        /// <param name="Length"></param>
        /// <returns></returns>
        public static string DelLastLength(this string str,int Length) {
            if(string.IsNullOrEmpty(str))
                return "";
            str = str.Substring(0,str.Length - Length);
            return str;
        }
		/// <summary>
        /// 删除 注释和空行
        /// </summary>
        public static string DelNote(this string instr) {
            string m_outstr = instr.Clone() as string;
            RegexOptions options = RegexOptions.Multiline | RegexOptions.IgnoreCase;
            //删除 /* */ 注释
            m_outstr = new Regex(@"\/\/[^\n]*|\/\*([^\*^\/]*|[\*^\/*]*|[^\**\/]*)*\*+\/",options).Replace(m_outstr,string.Empty);
            //删除<!-- --> 注释：
            m_outstr = new Regex(@"<!-[\s\S]*?-->",options).Replace(m_outstr,string.Empty);
            //删除 // 注释 ://也删除了
            m_outstr = new Regex(@"[^:]//{1,2}[\s\S]*?\n",options).Replace(m_outstr,string.Empty);
            //删除 -- SQL注释 
            m_outstr = new Regex(@"[\t]*--[^>][^\n]*\n",options).Replace(m_outstr,string.Empty);
            //删除空白行
            m_outstr = new Regex(@"^\s*\n",options).Replace(m_outstr,string.Empty);
            return m_outstr;
        }
		/// <summary>
        /// 删除HTML文本中的脚本样式注释空行
        /// </summary>
		public static string DelHTML(this string instr) {
            string m_outstr = instr.Clone() as string;
            m_outstr = new Regex(@"(?m)<script[^>]*>(\w|\W)*?</script[^>]*>",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"(?m)<style[^>]*>(\w|\W)*?</style[^>]*>",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"(?m)<link[^>]*>(\w|\W)*?[^>]*>",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"<iframe[\s\S]+</iframe *>",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"<frameset[\s\S]+</frameset  *>",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"-->",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"<!--.*",RegexOptions.Multiline | RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr = new Regex(@"(&nbsp;)+").Replace(m_outstr,"");
            m_outstr = new Regex(@"(\r\n\r\n)+").Replace(m_outstr,"");
            return m_outstr;
        }
        #endregion
        /// <summary>
        /// 判断字符串是否为Null、空
        /// string.IsNullOrWhiteSpace(s)
        /// </summary>
        public static bool IsNull(this string s) {
            return string.IsNullOrWhiteSpace(s);
        }
        /// <summary>
        /// 判断字符串是否不为Null、空 !string.IsNullOrWhiteSpace(s)
        /// </summary>
        public static bool NotNull(this string s) {
            return !string.IsNullOrWhiteSpace(s);
        }
        /// <summary>
        /// 去除所有空格
        /// </summary>
        public static string DelSpace(this string str) {
            if(str.IsNull()) return "";
            return str.Replace(" ","").Replace("\r","").Replace("\n","");
        }
        /// <summary>
        /// 替换字符串
        /// </summary>
        public static string ReplaceIgnoreCase(this string str,string oldString,string newString,StringComparison stringComparison = StringComparison.OrdinalIgnoreCase) {
            return str.IsNull() ? "" : str.Replace(oldString,newString,stringComparison);
        }
        /// <summary>
        /// 与字符串进行比较，忽略大小写
        /// </summary>
        /// <param name="s"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool EqualsIgnoreCase(this string s,string value) {
            return s.Equals(value,StringComparison.OrdinalIgnoreCase);
        }
    }
}